package top.eggcode.setup.config.session;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import top.eggcode.common.error.ApplicationException;
import top.eggcode.system.modules.user.model.AccountEntity;
import top.eggcode.system.modules.user.service.AccountServiceImpl;
import top.eggcode.system.modules.user.service.UserServiceImpl;

import java.util.Optional;

/**
 * Title: 会话身份
 * Description: TODO
 * Date: 2021/6/11 14:23
 *
 * @author JiaQi Ding
 * @version 1.0
 */
//@Component
@RequiredArgsConstructor
public class AppSessionRealm extends AuthorizingRealm {

    private final AccountServiceImpl accountService;

    private final UserServiceImpl userService;

    /**
     * 重写令牌类型的验证
     *
     * @param token 令牌
     * @return 结果
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 获取用户权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        Optional<AccountEntity> box = accountService.findByUsername(username);
        if (!box.isPresent()) {
            throw new ApplicationException("找不到账户信息");
        }
        AccountEntity account = box.get();

        SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();
        // 绑定角色码
        authorization.addRoles(userService.getRoleCodeList(account.getUsername()));
        // 绑定操作码
        authorization.addStringPermissions(
                userService.getPowerCodeList(account.getUsername())
        );
        return authorization;
    }

    /**
     * 获取用户身份
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        // 委托人
        String username = (String) authenticationToken.getPrincipal();

        // 凭证
        String token = String.valueOf((char[]) authenticationToken.getCredentials());

        // 没有登录标记
        if (StringUtils.isBlank(username)) {
            throw new IncorrectCredentialsException("无效 token");
        }

        return new SimpleAuthenticationInfo(
                username,
                token,
                getName());
    }
}
